package edu.cmich.cps.cps240.partyprincesspalace.hw06;

import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * An input/output pin which is "owned" by a wire.  It can only connect
 * to chips.
 * @author holde1ja
 */
public class WirePin implements Pin, Serializable{
	private static final long serialVersionUID = 5742521415826089674L;
	private String name;
	private Wire parent;
	private ChipPin partner;
	private Point location;
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#getParent()
	 */
	@Override
	public WorkspaceObj getParent() {
		return parent;
	}
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#setParent(edu.cmich.cps.cps240.partyprincesspalace.hw06.WorkspaceObj)
	 */
	@Override
	public void setParent(WorkspaceObj p_parent) {
		if(p_parent instanceof Wire) parent = (Wire) p_parent;
	}
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#getPartner()
	 */
	@Override
	public Pin getPartner() {
		return partner;
	}
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#setPartner(edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin)
	 */
	@Override
	public void setPartner(Pin p_partner) {
		if (p_partner == null)
		{
			partner = null;
			return;
		}
		if(p_partner instanceof ChipPin) partner = (ChipPin) p_partner;
	}
	
	/*
	 * dead code
	/**
	 * Returns the chip which is associated with this object.  Because WirePins
	 * can only connect to chips and can only be "owned" by wires, this returns
	 * the parent of the partner of the WirePin
	 * @return the chip which is connected to the chip, null if there is no connection
	 */
	/*@Override
	public Chip getChip() {
		if (partner == null)
		{
			return null;
		}
		if (partner.getParent() instanceof Chip){
			return (Chip) partner.getParent();
		}
		return null;
	}*/
	
	/*
	 * dead code
	/**
	 * Returns the wire which is associated with this object.  Because WirePins
	 * can only connect to chips, and can only be "owned" by wires, this returns
	 * the parent of the WirePin
	 * @return The wire which owns this WirePin.
	 */
	/*@Override
	public Wire getWire() {
		return parent;
	}
	*/
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#getName()
	 */
	@Override
	public String getName() {
		return name;
	}
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#setName(java.lang.String)
	 */
	@Override
	public void setName(String p_name) {
		if (p_name != null){
			name = p_name;
		}
	}
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#isInput()
	 */
	@Override
	public boolean isInput() {
		 return this.parent.isInputPin(this);
	}
	
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#isOutput()
	 */
	@Override
	public boolean isOutput() {
		int temp = this.parent.isOutputPin(this);
		 if (temp != -1) return true;
		 else{
			 return false;
		 }
	}
	
	
	/**
	 * Constructs a wire object by doing a dumb assignment to the parameters
	 * @param chipName The name which identifies this pin.
	 * @param wireParent The wire object which is to be the parent/owner.
	 * null if the pin is not currently assigned a parent/owner
	 * @param pinPartner The chip *PIN* which is to be connected to the pin.
	 * null if the pin is not connected to anything.
	 */
	public WirePin(String pinName, Wire wireParent, ChipPin chipPartner){
		if (pinName != null){
			this.name = pinName;
		}
		this.parent = wireParent;
		this.partner = chipPartner;
		location = new Point();
	}
	
	
	/**
	 * This constructor does not copy original, per se, it copies the
	 * name and parent of original.
	 * @param original (WirePin), duplicate some elements of this object (see above).
	 */
	public WirePin(WirePin original){
		if (original.name != null){
			this.name = original.name;
		}
		this.parent = original.parent;
		this.partner = null;
		location = new Point();
	}


	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#getLocation()
	 */
	@Override
	public Point getLocation() {
		return new Point(location);
	}

	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#setLocation(java.awt.Point)
	 */
	@Override
	public void setLocation(Point p_location) {
		if ((p_location.getX() >= 0)&&(p_location.getY() >= 0)){
			location = new Point(p_location);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see edu.cmich.cps.cps240.partyprincesspalace.hw06.Pin#closeToPin(java.awt.Point)
	 */
	@Override
	public boolean closeToPin(Point point) {
		if ((point.getX() < 0)||(point.getY() < 0)) return false;
		Rectangle rect = new Rectangle();
		rect.x = this.getLocation().x - 5;
		rect.y = this.getLocation().y - 5;
		rect.width = 10;
		rect.height = 10;
		return rect.contains(point);
	}
	
	/**
	 * Is necessary for the Serializable implementation. Passes a serialized version of the object to the
	 * ObjectOutputStream passed in as a parameter.
	 * @param out, an ObjectOutputStream to which the serialized version of this object is passed.
	 */
	@Override
	public void writeObject(ObjectOutputStream out) throws IOException
	{
		out.defaultWriteObject(); 
	}
	
	
	/**
	 * Is necessary for the Serializable implementation. Creates an object from the
	 * ObjectInputStream passed in as a parameter.
	 * @param in, an ObjectInputStream from which to create the object.
	 */
	@Override
	public void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
	{
		// our "pseudo-constructor"
		in.defaultReadObject();
	
	}
}